#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <unistd.h>
#include "ComputeTask.h"
#include "IOTask.h"

// 读取子进程写入的时间文件
void read_time_data(const char *filename, struct timeval *start, struct timeval *end) {
    FILE *fp = fopen(filename, "r");
    if (fp) {
        fscanf(fp, "%ld %ld %ld %ld", &start->tv_sec, &start->tv_usec, &end->tv_sec, &end->tv_usec);
        fclose(fp);
    }
}

int main(int argc, char *argv[]) {
    double computeTaskTimeElapse = 0.0;
    double IOTaskTimeElapse = 0.0;
    double totalTimeElapse = 0.0;
    struct timeval computeStart, computeEnd, ioStart, ioEnd;
    pid_t compute_pid, io_pid;

    // 创建计算任务子进程
    compute_pid = fork();
    if (compute_pid == 0) {
        struct timeval start, end;
        gettimeofday(&start, NULL);  // 记录任务开始时间
        executeComputeTask();         // 执行计算任务
        gettimeofday(&end, NULL);     // 记录任务结束时间
        // 将时间数据写入临时文件
        FILE *fp = fopen("compute_time.txt", "w");
        if (fp) {
            fprintf(fp, "%ld %ld %ld %ld", start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
            fclose(fp);
        }
        exit(0);
    } else if (compute_pid < 0) {
        perror("创建计算子进程失败");
        exit(1);
    }

    // 创建I/O任务子进程
    io_pid = fork();
    if (io_pid == 0) {
        struct timeval start, end;
        gettimeofday(&start, NULL);  // 记录任务开始时间
        executeIOTask();             // 执行I/O任务
        gettimeofday(&end, NULL);    // 记录任务结束时间
        // 将时间数据写入临时文件
        FILE *fp = fopen("io_time.txt", "w");
        if (fp) {
            fprintf(fp, "%ld %ld %ld %ld", start.tv_sec, start.tv_usec, end.tv_sec, end.tv_usec);
            fclose(fp);
        }
        exit(0);
    } else if (io_pid < 0) {
        perror("创建I/O子进程失败");
        exit(1);
    }

    // 父进程等待两个子进程结束
    waitpid(compute_pid, NULL, 0);
    waitpid(io_pid, NULL, 0);

    // 读取子进程的时间数据
    read_time_data("compute_time.txt", &computeStart, &computeEnd);
    read_time_data("io_time.txt", &ioStart, &ioEnd);

    // 计算各任务耗时
    computeTaskTimeElapse = (computeEnd.tv_sec - computeStart.tv_sec) +
                            (computeEnd.tv_usec - computeStart.tv_usec) / 1000000.0;
    IOTaskTimeElapse = (ioEnd.tv_sec - ioStart.tv_sec) +
                       (ioEnd.tv_usec - ioStart.tv_usec) / 1000000.0;

    // 计算总耗时（取两个任务的最大结束时间 - 最小开始时间）
    struct timeval earliestStart = (computeStart.tv_sec < ioStart.tv_sec) ? computeStart : ioStart;
    struct timeval latestEnd = (computeEnd.tv_sec > ioEnd.tv_sec) ? computeEnd : ioEnd;
    totalTimeElapse = (latestEnd.tv_sec - earliestStart.tv_sec) +
                      (latestEnd.tv_usec - earliestStart.tv_usec) / 1000000.0;

    // 输出结果
    printf("计算任务耗时: %.6f 秒\n", computeTaskTimeElapse);
    printf("I/O任务耗时: %.6f 秒\n", IOTaskTimeElapse);
    printf("总耗时（并行）: %.6f 秒\n", totalTimeElapse);

    // 清理临时文件
    remove("compute_time.txt");
    remove("io_time.txt");

    return 0;
}
